//////////////////////////////////////////////////////////////////////////////
//
//  Created by Philip Mulcahy on 13/01/2012.
//  Copyright (c) 2012 Philip Mulcahy. All rights reserved.
//
//  This file is part of the note-recog library.
//
//  note-recog is free software: you can redistribute it and/or modify
//  it under the terms of version 3 of the GNU Lesser General Public License 
//  as published by the Free Software Foundation.
//
//  note-recog is distributed is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with note-recog.  If not, see <http://www.gnu.org/licenses/>.
//
//////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include "NoteEvent.h"
#include <sstream>
#include <math.h>
#include "Log.h"

using namespace std;

LOG_DEFINE(NoteEvent);

NoteEvent::NoteEvent(float freq, double timeInSeconds) : 
  _freq(freq),
  _timeInSeconds(timeInSeconds)
{
    LOG_DEBUG( "NoteEvent(" << *this << ")" );
}

bool NoteEvent::isGood() const 
{ 
    return true; 
}

int NoteEvent::getNoteNumber() const
{ 
    const float ratio = _freq / 440.f;
    const float fnumber = ( log(ratio)/log(2.0f) * 12.0f ) + 0.5f;
    const int number = static_cast<int>(fnumber);
    return number;
}

float NoteEvent::getFrequency() const
{ 
    return _freq; 
}

string NoteEvent::getNoteString() const 
{ 
    const char * names[] = {"A","Bb","B","C","C#","D","D#","E","F","F#","G","Ab"};
    const int noteNumber = getNoteNumber();
    const int noteNumberMod = (noteNumber + (12*1000)) % 12;
    const char * sz = names[noteNumberMod];
    return string(sz);
}

double NoteEvent::getStartTime() const  
{
    return _timeInSeconds;
}

string NoteEvent::toString() const
{ 
    stringstream ss;
    ss.precision(4);
    
    ss << "NoteEvent{" 
       << getFrequency()  << "hz," 
       << getNoteNumber() << "," 
       << getNoteString() << ","
       << _timeInSeconds  << "}";
    
    return ss.str();
}

ostream& operator<<(ostream& os, const INoteEvent& evt)
{
    os << evt.toString();
    return os;
}